from fastapi import APIRouter, HTTPException, Query
from pydantic import BaseModel
import secrets
import time
from typing import Optional
from tools.third_party_login import ThirdPartyLoginManager
from tools.database_service import DatabaseService

# 创建路由器
third_party_auth = APIRouter()

# 临时存储授权状态和用户会话
auth_states = {}
user_sessions = {}

class ThirdPartyUser(BaseModel):
    id: str
    name: Optional[str] = None
    avatar_url: Optional[str] = None
    email: Optional[str] = None

class DingdingUser(ThirdPartyUser):
    unionid: Optional[str] = None
    mobile: Optional[str] = None

class GiteeUser(ThirdPartyUser):
    login: str
    bio: Optional[str] = None
    blog: Optional[str] = None
    company: Optional[str] = None
    location: Optional[str] = None
    public_repos: int = 0
    followers: int = 0
    following: int = 0

class LoginResponse(BaseModel):
    success: bool
    message: str
    user: Optional[ThirdPartyUser] = None
    dingding_user: Optional[DingdingUser] = None
    gitee_user: Optional[GiteeUser] = None
    access_token: Optional[str] = None
    platform: str

# 创建第三方登录管理器实例
login_manager = ThirdPartyLoginManager()

@third_party_auth.get("/auth/dingtalk/login")
async def dingtalk_login():
    """获取钉钉登录授权URL"""
    dingtalk_login = login_manager.get_login_instance("dingtalk")
    if not dingtalk_login:
        raise HTTPException(status_code=500, detail="钉钉登录服务不可用")

    result = dingtalk_login.get_auth_url()
    # 存储state用于验证
    auth_states[result["state"]] = {"timestamp": time.time(), "platform": "dingtalk"}

    return result

@third_party_auth.get("/auth/dingtalk/callback")
async def dingtalk_callback(code: Optional[str] = Query(None), auth_code: Optional[str] = Query(None), state: str = Query(...)):
    """处理钉钉授权回调"""
    try:
        # 兼容处理钉钉回调参数（钉钉可能返回 code 或 authCode）
        auth_code_param = code or auth_code

        if not auth_code_param:
            raise HTTPException(status_code=400, detail="缺少授权码参数")

        # 验证state参数
        if state not in auth_states:
            print(f"❌ 无效的状态参数: {state}")
            raise HTTPException(status_code=400, detail="状态参数无效，请重新发起钉钉登录获取新的授权链接")

        state_info = auth_states[state]
        if time.time() - state_info["timestamp"] > 300:  # 5分钟过期
            del auth_states[state]
            raise HTTPException(status_code=400, detail="状态已过期 - 请重新发起钉钉登录")

        del auth_states[state]

        # 获取钉钉登录实例
        dingtalk_login = login_manager.get_login_instance("dingtalk")
        if not dingtalk_login:
            raise HTTPException(status_code=500, detail="钉钉登录服务不可用")

        # 处理回调 - 添加更详细的错误处理
        print(f"🔍 处理钉钉回调: code={auth_code_param}, state={state}")
        result = await dingtalk_login.handle_callback(auth_code_param, state)

        if not result["success"]:
            error_msg = result["error"]
            print(f"❌ 钉钉API调用失败: {error_msg}")

            # 根据不同的错误类型返回更友好的错误信息
            if "不合法的临时授权码" in error_msg or "invalidParameter.authCode.notFound" in error_msg:
                raise HTTPException(
                    status_code=400,
                    detail="授权码已过期或无效，请重新发起钉钉登录获取新的授权码（钉钉授权码有效期只有5分钟）"
                )
            elif "accessToken" in error_msg and "missing" in error_msg:
                raise HTTPException(
                    status_code=400,
                    detail="无法获取钉钉访问令牌，请检查钉钉应用配置或重新授权"
                )
            elif "errorCode" in error_msg:
                raise HTTPException(
                    status_code=400,
                    detail="钉钉API调用失败，请检查网络连接和钉钉应用配置"
                )
            else:
                raise HTTPException(status_code=400, detail=f"钉钉授权失败: {error_msg}")

        print(f"✅ 钉钉API调用成功: {result['user']}")

        # 创建用户对象
        dingtalk_user = DingdingUser(**result["user"])

        # 使用数据库服务处理钉钉登录或注册
        db_result = await DatabaseService.dingtalk_login_or_register(result["user"])

        if not db_result["success"]:
            error_msg = db_result["error"]
            print(f"❌ 数据库操作失败: {error_msg}")
            raise HTTPException(status_code=500, detail=f"数据库操作失败: {error_msg}")

        # 生成会话token
        session_token = secrets.token_urlsafe(32)
        user_sessions[session_token] = {
            "user": dingtalk_user,
            "timestamp": time.time(),
            "platform": "dingtalk",
            "user_id": db_result["user"]["id"],
            "is_new_user": db_result.get("is_new_user", False)
        }

        print(f"✅ 钉钉登录成功: 用户ID={db_result['user']['id']}, 用户名={dingtalk_user.name}")

        return LoginResponse(
            success=True,
            message=db_result["message"],
            dingding_user=dingtalk_user,
            access_token=session_token,
            platform="dingtalk"
        )

    except HTTPException:
        raise  # 重新抛出HTTP异常
    except Exception as e:
        print(f"❌ 钉钉回调处理异常: {e}")
        import traceback
        traceback.print_exc()
        raise HTTPException(status_code=500, detail=f"服务器内部错误: {str(e)}")

@third_party_auth.get("/auth/gitee/login")
async def gitee_login():
    """获取Gitee登录授权URL"""
    gitee_login = login_manager.get_login_instance("gitee")
    if not gitee_login:
        raise HTTPException(status_code=500, detail="Gitee登录服务不可用")

    result = gitee_login.get_auth_url()
    # 存储state用于验证
    auth_states[result["state"]] = {"timestamp": time.time(), "platform": "gitee"}

    return result

@third_party_auth.get("/auth/gitee/callback")
async def gitee_callback(code: str = Query(...), state: str = Query(...)):
    """处理Gitee授权回调"""
    try:
        # 验证state参数
        if state not in auth_states:
            raise HTTPException(status_code=400, detail="无效的状态参数")

        state_info = auth_states[state]
        if time.time() - state_info["timestamp"] > 300:  # 5分钟过期
            del auth_states[state]
            raise HTTPException(status_code=400, detail="状态已过期")

        del auth_states[state]

        # 获取Gitee登录实例
        gitee_login = login_manager.get_login_instance("gitee")
        if not gitee_login:
            raise HTTPException(status_code=500, detail="Gitee登录服务不可用")

        # 处理回调 - 添加更详细的错误处理
        print(f"🔍 处理Gitee回调: code={code}, state={state}")
        result = await gitee_login.handle_callback(code, state)

        if not result["success"]:
            error_msg = result["error"]
            print(f"❌ Gitee API调用失败: {error_msg}")

            # 根据不同的错误类型返回更友好的错误信息
            if "token error" in error_msg or "unauthorized" in error_msg:
                raise HTTPException(
                    status_code=400,
                    detail="无法获取Gitee访问令牌，请检查Gitee应用配置或重新授权"
                )
            elif "API error" in error_msg:
                raise HTTPException(
                    status_code=400,
                    detail="Gitee API调用失败，请检查网络连接和Gitee应用配置"
                )
            else:
                raise HTTPException(status_code=400, detail=f"Gitee授权失败: {error_msg}")

        print(f"✅ Gitee API调用成功: {result['user']}")

        # 创建用户对象
        gitee_user = GiteeUser(**result["user"])

        # 使用数据库服务处理Gitee登录或注册
        db_result = await DatabaseService.gitee_login_or_register(result["user"])

        if not db_result["success"]:
            error_msg = db_result["error"]
            print(f"❌ 数据库操作失败: {error_msg}")
            raise HTTPException(status_code=500, detail=f"数据库操作失败: {error_msg}")

        # 生成会话token
        session_token = secrets.token_urlsafe(32)
        user_sessions[session_token] = {
            "user": gitee_user,
            "timestamp": time.time(),
            "platform": "gitee",
            "user_id": db_result["user"]["id"],
            "is_new_user": db_result.get("is_new_user", False)
        }

        print(f"✅ Gitee登录成功: 用户ID={db_result['user']['id']}, 用户名={gitee_user.name}")

        return LoginResponse(
            success=True,
            message=db_result["message"],
            gitee_user=gitee_user,
            access_token=session_token,
            platform="gitee"
        )

    except HTTPException:
        raise  # 重新抛出HTTP异常
    except Exception as e:
        print(f"❌ Gitee回调处理异常: {e}")
        import traceback
        traceback.print_exc()
        raise HTTPException(status_code=500, detail=f"服务器内部错误: {str(e)}")

@third_party_auth.get("/auth/user/info")
async def get_user_info(token: str = Query(...)):
    """获取当前登录用户信息"""
    if token not in user_sessions:
        raise HTTPException(status_code=401, detail="无效或过期的令牌")

    session = user_sessions[token]
    # 检查会话是否过期（24小时）
    if time.time() - session["timestamp"] > 86400:
        del user_sessions[token]
        raise HTTPException(status_code=401, detail="令牌已过期")

    return {
        "success": True,
        "user": session["user"],
        "platform": session["platform"]
    }

@third_party_auth.post("/auth/logout")
async def logout(token: str = Query(...)):
    """用户登出"""
    if token in user_sessions:
        del user_sessions[token]

    return {"success": True, "message": "登出成功"}

@third_party_auth.get("/auth/dingtalk/user/info")
async def get_dingtalk_user_info(token: str = Query(...)):
    """获取当前钉钉登录用户信息"""
    if token not in user_sessions:
        raise HTTPException(status_code=401, detail="无效或过期的令牌")

    session = user_sessions[token]
    # 检查会话是否过期（24小时）
    if time.time() - session["timestamp"] > 86400:
        del user_sessions[token]
        raise HTTPException(status_code=401, detail="令牌已过期")

    user_id = session.get("user_id")
    if not user_id:
        raise HTTPException(status_code=500, detail="会话信息不完整")

    # 从数据库获取完整的用户信息和第三方登录信息
    db_stats = await DatabaseService.get_database_stats()
    user_third_party = await DatabaseService.get_user_third_party_logins(user_id)

    return {
        "success": True,
        "message": "获取用户信息成功",
        "session_info": {
            "user_id": user_id,
            "is_new_user": session.get("is_new_user", False),
            "platform": session.get("platform"),
            "login_time": session.get("timestamp")
        },
        "database_stats": db_stats.get("stats") if db_stats["success"] else None,
        "third_party_logins": user_third_party.get("third_party_logins") if user_third_party["success"] else []
    }

@third_party_auth.get("/auth/database/stats")
async def get_database_stats():
    """获取数据库统计信息"""
    result = await DatabaseService.get_database_stats()
    if result["success"]:
        return result
    else:
        raise HTTPException(status_code=500, detail=result["error"])
